package com.app.dao;

import com.app.SpringAnnotationDef;
import com.app.model.User;
import com.app.utils.Pager;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: mosg
 * Date: 12-3-3
 * Time: 下午5:07
 * To change this template use File | Settings | File Templates.
 */
@Scope(SpringAnnotationDef.SCOPE_PROTOTYPE)
@Transactional
public class BaseDaoImpl<T extends Serializable, ID extends Serializable> implements BaseDao<T, ID> {


    protected Class<T> entity;

    @Resource(name = "sessionFactory")
    private SessionFactory sessionFactory;
    //由于spring3和hibernate4的集成部是很完善 只能使用hibernate的自有的session来操作。所有也提供了 下面的jdbc对象。


    @Resource(name = "jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public BaseDaoImpl(Class<T> entityClass) {
        this.entity = entityClass;
    }

    @Override
    public T save(T model) {
        return (T) getSession().save(model);
    }

    @Override
    public void saveObject(Object obj) {
        getSession().saveOrUpdate(obj);
    }

    @Override
    public void saveOrUpdate(T model) {
        getSession().saveOrUpdate(model);
    }

    @Override
    public void update(T model) {
        getSession().update(model);
    }

    @Override
    public void merge(T model) {
        getSession().merge(model);
    }

    @Override
    public void delete(ID id) {
        getSession().delete(this.get(id));
    }

    @Override
    public void deleteObject(T model) {
        getSession().delete(model);
    }

    @Override
    public T get(ID id) {
        return (T) getSession().get(this.entity, id);
    }

    @Override
    public int countAll() {


        return 0;
    }

    @Override
    public List<T> listAll() {
        return (List<T>) getSession().createCriteria(this.entity).addOrder(Order.asc("id")).list();
    }

    @Override
    public List<T> listAll(int pageNum, int pageSize) {
        Criteria criteria = getSession().createCriteria(this.entity);
        criteria.setFirstResult((pageNum - 1) * pageSize + 1);
        criteria.setMaxResults(pageSize);
        return (List<T>) criteria.list();//(List<T>)getSession().createCriteria(this.entity).setFirstResult().list();
    }

    @Override
    public List<T> pre(ID id, int pageNum, int pageSize) {
        return null;
    }

    @Override
    public List<T> next(ID id, int pageNum, int pageSize) {
        return null;
    }

    @Override
    public boolean exists(ID id) {
        return get(id) != null;
    }

    @Override
    public void flush() {
        getSession().flush();
    }

    @Override
    public void clear() {
        getSession().clear();
    }

    @Override
    public Pager pagerList(Pager pager) {
        Criteria criteria = getSession().createCriteria(this.entity);
        return findPager(pager, criteria);

    }

    public Pager findPager(Pager pager, Criteria criteria) {
        Integer pageNumber = pager.getPageNumber();
        Integer pageSize = pager.getPageSize();
        String searchBy = pager.getSearchBy();
        String keyword = pager.getKeyword();
        String orderBy = pager.getOrderBy();
        Pager.Order order = pager.getOrder();

        if (StringUtils.isNotEmpty(searchBy) && StringUtils.isNotEmpty(keyword)) {
            if (searchBy.contains(".")) {
                String alias = StringUtils.substringBefore(searchBy, ".");
                criteria.createAlias(alias, alias);
            }
            criteria.add(Restrictions.like(searchBy, "%" + keyword + "%"));
        }

        //总数                                 addOrder(Order.asc("id")).list();
        pager.setTotalCount(criteria.list().size());

        //排序
        if (StringUtils.isNotEmpty(orderBy) && order != null) {
            if (order == Pager.Order.asc) {
                criteria.addOrder(Order.asc(orderBy));
            } else {
                criteria.addOrder(Order.desc(orderBy));
            }
        }
/*
        ClassMetadata classMetadata = getSessionFactory().getClassMetadata(
                entityClass);
        if (!StringUtils.equals(orderBy, ORDER_LIST_PROPERTY_NAME)
                && ArrayUtils.contains(classMetadata.getPropertyNames(),
                ORDER_LIST_PROPERTY_NAME)) {
            criteria.addOrder(Order.asc(ORDER_LIST_PROPERTY_NAME));
            criteria.addOrder(Order.desc(CREATE_DATE_PROPERTY_NAME));
            if (StringUtils.isEmpty(orderBy) || order == null) {
                pager.setOrderBy(ORDER_LIST_PROPERTY_NAME);
                pager.setOrder(Pager.Order.asc);
            }
        } else if (!StringUtils.equals(orderBy, CREATE_DATE_PROPERTY_NAME)
                && ArrayUtils.contains(classMetadata.getPropertyNames(),
                CREATE_DATE_PROPERTY_NAME)) {
            criteria.addOrder(Order.desc(CREATE_DATE_PROPERTY_NAME));
            if (StringUtils.isEmpty(orderBy) || order == null) {
                pager.setOrderBy(CREATE_DATE_PROPERTY_NAME);
                pager.setOrder(Pager.Order.desc);
            }
        }*/
        criteria.setFirstResult((pageNumber - 1) * pageSize);
        criteria.setMaxResults(pageSize);

        pager.setResult(criteria.list());
        return pager;
    }


    public Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    public HibernateTemplate getHibernateTemplate() {
        HibernateTemplate template = new HibernateTemplate(sessionFactory);
        return template;
    }
}
